home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Ken Long / NewRotation-c / Think / Rotation.c next >
Encoding:
Text File  |  1994-12-04  |  12.0 KB  |  425 lines  |  [TEXT/KAHL]

  1. // ------------------------------------------------------------------- //
  2. // Another public domain C example source demo, brought back from        //
  3. // the dead at:  itty bitty bytes™ - by Kenneth A. Long!                //
  4. // Made to run in Think C™ on 2 June 1994.                                //
  5. // Uses no resource file - just add MacTraps and ANSI libraries.        //
  6. // The original of this file was found on ftp.cso.uiuc.edu in mac/MUG. //
  7. // ------------------------------------------------------------------- //
  8. // Update, 22 September 1994, to include Offscreen GWorld, key
  9. // controls and eliminate flicker.
  10. // kenlong@netcom.com
  11. // ------------------------------------------------------------------- //
  12.  
  13. #include <stdio.h>    
  14. #include <math.h>
  15. #include <qdoffscreen.h>
  16.  
  17.  
  18. #define LEFT 0    
  19. #define TOP 0    
  20. #define RIGHT qd.screenBits.bounds.right    
  21. #define BOTTOM qd.screenBits.bounds.bottom   
  22.  
  23. #define X 0    
  24. #define Y 1
  25. #define Z 2 
  26. #define  NMBR_FACES 9
  27. #define  NMBR_VERTICES 9
  28. #define  NMBR_SETS 20
  29. #define LX 80
  30. #define LY 40
  31. #define LZ 60    
  32.  
  33. #define SOLID_LIGHT 0
  34. #define SOLID  1
  35. #define WIRE_FRAME 2
  36.  
  37.  
  38. short vertex [NMBR_VERTICES] [3] = 
  39. {            
  40.     {            0,         0,       LZ / 2 }, 
  41.     {       LX / 2,         0,           LZ },     
  42.     {           LX,         0,       LZ / 2 }, 
  43.     {       LX / 2,         0,            0 }, 
  44.     {      LX / 2,        LY,       LZ / 4 },     
  45.     { 3 * LX / 4,        LY,       LZ / 2 },     
  46.     {      LX / 2,        LY, 3 * LZ / 4},     
  47.     {      LX / 4,        LY,       LZ / 2 }, 
  48.     {      LX / 2, -LY / 2,       LZ / 2 }
  49. };    
  50.  
  51. short  face [NMBR_FACES] [5] = 
  52. {     
  53.     {0, 1, 6, 7, 0}, 
  54.     {1, 2, 5, 6, 1}, 
  55.     {2, 3, 4, 5, 2}, 
  56.     {7, 4, 3, 0, 7}, 
  57.     {7, 6, 5, 4, 7}, 
  58.     {0, 3, 8, 0}, 
  59.     {8, 1, 0, 8}, 
  60.     {8, 2, 1, 8}, 
  61.     {8, 3, 2, 8}
  62. };
  63.         
  64. short  xr = 200, yr = 160, zr = 0, dxo = 50, dyo = 30, dzo = -50;    
  65. PolyHandle  face_poly [NMBR_SETS] [NMBR_FACES];
  66. short visible [NMBR_SETS] [NMBR_FACES];    
  67. short light [NMBR_SETS] [NMBR_FACES];    
  68. short drawflag;
  69.  
  70. Rect option_rect, display_rect;
  71.  
  72. WindowPtr    newWindow;                           
  73. Rect        windowBounds;
  74.  
  75. //• GWorld goodies.
  76. GWorldPtr        gOffscreenGWorld;    
  77. Rect            gOnscreenRect;    // The "projection screen" area in the window
  78. Rect            gOffscreenRect;
  79.  
  80. //• MBar hide/show stuff.
  81. RgnHandle        mBarRgn, GrayRgn;
  82. short            *mBarHeightPtr;
  83. short            oldMBarHeight;
  84.  
  85. GWorldPtr Create_A_GWorld (Rect *theRect);
  86. void New_Window (void);
  87. void main (void);
  88. void Compute_Rotation_Data (short axis);
  89. void Rotate_Object (void);
  90.  
  91. void HideMenuBar (void) 
  92. {
  93.     Rect    mBarRect;
  94.  
  95.     GrayRgn = GetGrayRgn ();
  96.     mBarHeightPtr = (short *)  0x0BAA;
  97.     oldMBarHeight = *mBarHeightPtr;
  98.     *mBarHeightPtr = 0;
  99.     mBarRect = qd.screenBits.bounds;
  100.     mBarRect.bottom = mBarRect.top + oldMBarHeight;
  101.     mBarRgn = NewRgn ();
  102.     RectRgn (mBarRgn, &mBarRect);
  103.     UnionRgn (GrayRgn, mBarRgn, GrayRgn);
  104.     PaintOne (0L, mBarRgn);
  105. }
  106.  
  107. void ShowMenuBar (void) 
  108. {
  109.     *mBarHeightPtr = oldMBarHeight;
  110.     DiffRgn (GrayRgn, mBarRgn, GrayRgn);
  111.     DisposeRgn (mBarRgn);
  112. }
  113.  
  114. GWorldPtr Create_A_GWorld (Rect *theRect)
  115. {
  116.     CGrafPtr    currentPort;
  117.     GDHandle    currentGDevice;
  118.     GWorldPtr   offScreen;
  119.     QDErr       result;
  120.  
  121.     GetGWorld (¤tPort, ¤tGDevice);
  122.     
  123.     if ((result = NewGWorld (&offScreen, 0, theRect, nil, nil, 0L)) != noErr)
  124.         if ((result = NewGWorld (&offScreen, 0, theRect, nil, nil, useTempMem)) != noErr)
  125.             return (nil);
  126.             
  127.     SetGWorld (offScreen, nil);
  128.  
  129.     ClipRect (&offScreen->portRect);    
  130.     
  131.     if (LockPixels (GetGWorldPixMap (offScreen)))
  132.     {
  133.         ForeColor (blackColor);
  134.         BackColor (whiteColor);
  135.         EraseRect (&offScreen->portRect);
  136.         UnlockPixels (GetGWorldPixMap (offScreen));
  137.     }
  138.  
  139.     SetGWorld (currentPort, currentGDevice);
  140.     return offScreen;
  141. }
  142.  
  143. void New_Window (void)
  144. {
  145.     SetRect (&windowBounds, LEFT, TOP, RIGHT, BOTTOM);
  146.     
  147.     newWindow = NewWindow (0L, &windowBounds, "\p3D Display", true, noGrowDocProc, (WindowPtr) - 1L, true, 0);
  148.     SetPort (newWindow);
  149.  
  150.     SetRect (&gOnscreenRect, LEFT, TOP + 20, RIGHT, BOTTOM + 20);
  151.     SetRect (&gOffscreenRect, LEFT, TOP + 20, RIGHT, BOTTOM + 20);
  152.  
  153.     gOffscreenGWorld = (GWorldPtr) Create_A_GWorld (&gOffscreenRect);
  154. }
  155.  
  156. void main ()                        
  157. {    
  158.     EventRecord the_event;
  159.     Point mousepoint;
  160.     GrafPtr the_port;
  161.     short i, j;
  162.     register short  this_set, next_set;
  163.     Rect temp_rect;
  164.     
  165.     InitGraf (&qd.thePort);     
  166.     InitFonts ();    
  167.     InitWindows ();    
  168.     InitCursor ();
  169.     
  170.     HideMenuBar ();
  171.     HideCursor ();
  172.     New_Window ();
  173.     
  174.     Compute_Rotation_Data (X);
  175.       drawflag = SOLID_LIGHT;
  176.     
  177.  
  178.     for (;;)
  179.     {    
  180.         GetNextEvent (everyEvent, &the_event);
  181.         if (the_event.what == keyDown)
  182.         {    
  183.             switch (the_event.message & charCodeMask)
  184.             {
  185.                 case 'Q':
  186.                 case 'q':
  187.                     ExitToShell ();
  188.                 break;
  189.  
  190.                 case 'x':
  191.                 case 'X':
  192.                     Compute_Rotation_Data (0);
  193.                 break;
  194.  
  195.                 case 'y':
  196.                 case 'Y':
  197.                     Compute_Rotation_Data (1);
  198.                 break;
  199.  
  200.                 case 'z':
  201.                 case 'Z':
  202.                     Compute_Rotation_Data (2);
  203.                 break;
  204.  
  205.                 case 'f':
  206.                 case 'F':
  207.                         if (++drawflag == 3)     
  208.                             drawflag = 0;
  209.                 break;
  210.             }
  211.         }
  212.         Rotate_Object ();
  213.     }
  214.     ShowCursor ();
  215.     ShowMenuBar ();
  216. }
  217.  
  218. void Compute_Rotation_Data (short axis)
  219. {
  220.     register short this_set, i, j;
  221.     short  basev [NMBR_VERTICES] [3];
  222.     short v [NMBR_VERTICES] [3];
  223.     short p_vx [NMBR_VERTICES], p_vy [NMBR_VERTICES];
  224.     short ax, ay, az, bx, by, bz;
  225.     
  226.     Rect count_rect;                
  227.     short v0, v1, v2;
  228.     float sin_table, cos_table; 
  229.     #define D_THETA  6.283185 / NMBR_SETS
  230.     
  231.     SetRect (&count_rect, 0, 21, 512, 342);    
  232.     EraseRect (&count_rect);
  233.     TextSize (18); 
  234.     TextFace (bold); 
  235.     TextFont (geneva); 
  236.     PenNormal ();
  237.     MoveTo (30, 50);    
  238.     DrawString ("\pComputation of Rotation Data");
  239.     MoveTo (30, 80);    
  240.     DrawString ("\pCounting Down...");
  241.         
  242.     for (i = 0; i < NMBR_VERTICES; ++i)    
  243.     {    
  244.         basev [i] [X] = vertex [i] [X]  + dxo;    
  245.         basev [i] [Y] = vertex [i] [Y]  + dyo;    
  246.         basev [i] [Z] = vertex [i] [Z]    + dzo;
  247.     }
  248.     
  249.     for (this_set = 0; this_set < NMBR_SETS; ++this_set)    
  250.     { 
  251.         sin_table  =  sin (D_THETA * this_set);    
  252.         cos_table = cos (D_THETA * this_set);    
  253.         
  254.         for (i = 0; i < NMBR_VERTICES; ++i)    
  255.         {    
  256.             switch (axis)    
  257.             {    
  258.                 case Z:    
  259.                     v [i] [X] = basev [i] [X] * 
  260.                               cos_table - basev [i] [Y] *
  261.                               sin_table;
  262.                               
  263.                     v [i] [Y] = basev [i] [X] *
  264.                               sin_table + basev [i] [Y] *
  265.                               cos_table;
  266.                               
  267.                     v [i] [Z] = basev [i] [Z];
  268.                 break;
  269.                 
  270.                 case Y:    
  271.                     v [i] [X] = basev [i] [X] * 
  272.                               cos_table + basev [i] [Z] * sin_table;
  273.                               
  274.                     v [i] [Y] = basev [i] [Y];
  275.                     v [i] [Z] = -basev [i] [X] * 
  276.                               sin_table + basev [i] [Z] * cos_table;
  277.                 break;
  278.                 
  279.                 case X:    
  280.                     v [i] [X] = basev [i] [X];
  281.                     v [i] [Y] = basev [i] [Y] * 
  282.                               sin_table +  basev [i] [Z] * cos_table;
  283.                     v [i] [Z] = -basev [i] [Y] * 
  284.                               cos_table +  basev [i] [Z] * sin_table;
  285.                     break;
  286.             }
  287.         }
  288.         for (i = 0; i < NMBR_FACES; ++i)
  289.         {    
  290.             v0 = face [i] [0];        
  291.             v1 = face [i] [1];    
  292.             v2 = face [i] [2];    
  293.             ay = v [v2] [Y] -  v [v1] [Y];    
  294.             by = v [v0] [Y] -  v [v1] [Y];
  295.             az =  v [v2] [Z] -  v [v1] [Z];    
  296.             bz =  v [v0] [Z] -  v [v1] [Z];
  297.         
  298.             light [this_set] [i] = (ay * bz - az * by) > 0 ?0 :1;    
  299.         }        
  300.         for (i = 0; i < NMBR_VERTICES; ++i)
  301.         {    
  302.             p_vx [i] = xr + .86603 * (v [i] [X] + v [i] [Z]);
  303.             p_vy [i] = yr +  v [i] [Y] + (v [i] [X] - v [i] [Z])/2;
  304.         }    
  305.         for (i = 0; i < NMBR_FACES; ++i)
  306.         {    
  307.             v0 = face [i] [0];        
  308.             v1 = face [i] [1];    
  309.             v2 = face [i] [2];    
  310.             ax = p_vx [v2] -  p_vx [v1];    
  311.             bx = p_vx [v0] -  p_vx [v1];
  312.             ay = p_vy [v2] -  p_vy [v1];    
  313.             by = p_vy [v0] -  p_vy [v1];
  314.         
  315.             visible [this_set] [i] =     (ax * by - ay * bx) < 0 ?1 :0;
  316.         }
  317.         for (i = 0; i < NMBR_FACES; ++i)
  318.         {    
  319.             face_poly [this_set] [i] = OpenPoly ();
  320.                 MoveTo (p_vx [face [i] [0]], p_vy [face [i] [0]] );
  321.                 for (j = 1; j < NMBR_VERTICES; ++j)
  322.                 {    
  323.                     LineTo (p_vx [face [i] [j]], p_vy [face [i] [j]] );
  324.                     if (face [i] [j] == face [i] [0] )    
  325.                         break;
  326.                 }
  327.                 ClosePoly ();
  328.         }
  329.         SetRect (&count_rect, 200, 50, 250, 80);
  330.         EraseRect (&count_rect);
  331.         MoveTo (200, 80);
  332.         i = (NMBR_SETS-this_set); 
  333.         if (i > 99)    
  334.             DrawChar (48 + i / 100);    
  335.         else    
  336.             DrawChar (' '); 
  337.         
  338.         if (i > 99)  
  339.         { 
  340.             i %= 100;      
  341.             DrawChar (48 + i / 10);  
  342.             i %= 10 ;  
  343.         }    
  344.         else
  345.             {    
  346.                 if (i>9)    
  347.                 {
  348.                     DrawChar (48 + i / 10);    
  349.                     i %= 10;  
  350.                 } 
  351.                 else  
  352.                     DrawChar (' '); 
  353.         }    
  354.         DrawChar (48 + i);
  355.     }
  356.     Draw_Option_Bar ();
  357. }    
  358.  
  359. Draw_Option_Bar ()
  360. {
  361.     TextSize (12);    
  362.     SetRect (&option_rect, 0, 0, 20, 420);    
  363.     
  364.     MoveTo (5, 16);    
  365.     DrawString ("\p Q - Quits, X - 'X' axis, Y - 'Y' axis, Z - 'Z' axis and F is Frame.");
  366. }
  367.     
  368. void Rotate_Object ()
  369. {    
  370.     long                ticksNow;
  371.     GWorldPtr            windowGW;
  372.     GDHandle            windowGD;
  373.     PixMapHandle        thePixMap;
  374.  
  375.     register             short i;    
  376.     static short             set = 0;
  377.     register PolyHandle *poly;
  378.     
  379.     poly = &face_poly [set] [0];
  380.     
  381.     GetGWorld (&windowGW, &windowGD);     // Save whatever we had before
  382.  
  383.     SetGWorld (gOffscreenGWorld, nil);
  384.  
  385.     if (LockPixels (thePixMap = GetGWorldPixMap (gOffscreenGWorld)))
  386.     {
  387.         EraseRect (&gOffscreenGWorld->portRect);
  388.         if (drawflag == SOLID_LIGHT)  
  389.         {    
  390.             for (i=0;i<NMBR_FACES;++i)    
  391.             {    
  392.                 if (visible [set] [i] ==1) 
  393.                 {    
  394.                     if (light [set] [i] ==1)     
  395.                         FillPoly (* (poly + i), &qd.ltGray);
  396.                         FramePoly (* (poly + i)); 
  397.                 }    
  398.             }
  399.         }
  400.         else 
  401.             if (drawflag == SOLID)  
  402.             {    
  403.                 for (i = 0; i < NMBR_FACES; ++i)    
  404.                     if (visible [set] [i] ==1)    
  405.                         FramePoly (* (poly + i)); 
  406.             }
  407.             else     
  408.                 for (i = 0; i < NMBR_FACES; ++i)    
  409.                     FramePoly (* (poly + i)); 
  410.         
  411.         if (++set == NMBR_SETS)    
  412.             set = 0;
  413.  
  414.         SetGWorld (windowGW, windowGD);
  415.  
  416.         CopyBits ((BitMap*) *thePixMap, 
  417.                 & ((GrafPtr) newWindow)->portBits, 
  418.                   &gOffscreenRect, 
  419.                   &gOnscreenRect, srcCopy, nil);
  420.         
  421.         UnlockPixels (thePixMap);
  422.     }
  423.     SetGWorld (windowGW, windowGD);
  424. }
  425.